/*
ID: icerupt1
PROG: wormhole
LANG: C++11
*/
#include <fstream>
#include <algorithm>
using namespace std;

struct data { int x; int y; };

int const maxn = 30;
int map[maxn][maxn];
data da[maxn];
int ans, n;

void init_map()
{
}

bool vis[maxn];
bool dfs_vis[maxn];

bool dfs(int now)
{
	dfs_vis[now] = true;
	for (int i = 0; i < 2*n; i++)
		if (map[now][i] > 0 && (dfs_vis[i] || dfs(i))) return true;
	return false;
}

bool has_circle()
{
	for (int i = 0; i < n; i++) {
		fill(dfs_vis, dfs_vis+2*n, false);
		if (dfs(i)) return true;
	}
	return false;
}

void select_pair(int deep, int index)
{
	if (deep == n/2) { if (has_circle()) ans++; return; }
	int first = index + 1;
	for (; first < n; first++) if (!vis[first]) break;
	for (int i = first + 1; i < n; i++)
		if (!vis[i]) {
			vis[i] = true; map[first][i + n]++; map[i][first + n]++;
			select_pair(deep+1, first);
			map[first][i + n]--; map[i][first + n]--; vis[i] = false;
		}
}

int main()
{
	ifstream fin {"wormhole.in" };
	ofstream fout{"wormhole.out"};

	fin >> n;
	for (int i = 0; i < n; i++) fin >> da[i].x >> da[i].y;

	sort(da, da+n, [](data a, data b){
		return a.y < b.y || (a.y == b.y && a.x < b.x);
	});

	for (int i = 1; i < n; i++)
		if (da[i].y == da[i-1].y) map[i-1 + n][i]++;
	select_pair(0, -1);
	fout << ans << "\n";
}
